package steffen;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import marcel.Lager;
import marja.KundenArchiv;

/**
 * Klasse, die eine Textdatei mit Befehlen einlesen und verarbeiten kann.
 * 
 * @author Steffen Krüger
 * @version 1.0
 */
public class BatchReader
{
    /**
     * Speichert den Pfad zur einzulesenden Datei
     */
    private String filename;

    /**
     * Konstruktor
     * 
     * @author Steffen Krüger
     * @param Stringfilename
     * @return
     */
    public BatchReader(String filename)
    {
        this.filename = filename;
    }

    /**
     * Einlesen einer Datei in die Batchverarbeitung
     * 
     * @author Steffen Krüger
     * @param
     * @return
     * @throws WSVException 
     */
    public void starteEinlesen() throws WSVException
    {
        /*
         * Benötigte Variablen definieren
         */
        InputStreamReader isr = null;
        File file = null;

        /*
         * Die Datei öffnen
         */
        try
        {   
            file                = new File(this.filename);
            FileInputStream fis = new FileInputStream(file);
            isr                 = new InputStreamReader(fis, Charset.forName("ISO-8859-1"));
            
        } catch (FileNotFoundException e)
        {
            /*
             * Datei konnte nicht gefunden werden
             */
            throw new WSVException("Datei " + file.getAbsoluteFile() + " wurde nicht gefunden.", -1);
        }

        /*
         * Einlesen der Datei vorbereiten
         */
        BufferedReader inFile = new BufferedReader(isr);
        String aktline = "";

        /*
         * IO Fehler abfangen
         */
        try
        {
            /*
             * Erste Zeile einlesen
             */
            try
            {
                aktline = new String(inFile.readLine().getBytes("UTF-8"));
            }
            catch(Exception e)
            {
               inFile.close();
               throw new WSVException("Es konnten keine Befehle in der übergebenen Datei gefunden werden.", 1);
            }
            
            do
            {
                /*
                 * Aktuelle Zeile verarbeiten
                 */
                String[] tokens = null;
                
                try
                {
                    tokens = aktline.trim().split("\\s+");
                }
                catch(Exception e)
                {
                   inFile.close();
                   throw new WSVException("Es konnten keine Befehle in der übergebenen Datei gefunden werden.", 1);
                }

                /*
                 * Aktuelle Verarbeitung ausgeben
                 */
                System.out.println("Zeile \"" + aktline.trim() + "\" wird verarbeitet");

                /*
                 * Wurde ein gültiger Befehl übergeben?
                 */
                switch (tokens[0].toLowerCase())
                {
                    case "a":
                    case "add":
                        /*
                         * Kunden hinzufügen
                         */
                        kundenHinzufügen(tokens);
                        break;
                    case "l":
                    case "lend":
                        /*
                         * Leihvorgang starten
                         */
                        ausleihen(tokens);
                        break;
                    case "r":
                    case "return":
                        /*
                         * Rückgabe starten
                         */
                        zurückgeben(tokens);
                        break;
                    case "s":
                    case "show":
                        /*
                         * Sind genügend Argumente für diese Befehle vorhanden?
                         */
                        Functions.prüfeArrayLänge(2, tokens);

                        /*
                         * Anzeigen
                         */
                        switch (tokens[1].toLowerCase())
                        {
                            case "c":
                            case "customer":
                                /*
                                 * Customer Anzeigen
                                 */
                                zeigeCustomer(tokens);
                                break;
                            case "o":
                            case "object":
                                /*
                                 * Objekte anzeigen
                                 */
                                zeigeObjekt(tokens);
                                break;
                            default:
                                /*
                                 * Unbekannter Befehl oder leere Zeile
                                 */
                                if (!aktline.isEmpty())
                                {
                                    throw new WSVException("Unbekannter Befehl: " + tokens[1], 1);
                                }
                                break;
                        }
                        break;
                    case "b":
                    case "bill":
                        /*
                         * Abrechnung
                         */
                        abrechnen(tokens);
                        break;
                    default:
                        /*
                         * Unbekannter Befehl oder leere Zeile
                         */
                        if (!aktline.isEmpty())
                        {
                            throw new WSVException("Unbekannter Befehl: " + tokens[0], 1);
                        }
                        break;
                }

                /*
                 * Nächste Zeile einlasen
                 */
                try
                {
                    aktline = new String(inFile.readLine().getBytes("UTF-8"));
                }catch(Exception e)
                {
                    aktline = null;
                }
            } while (aktline != null);

            /*
             * Datei schließen
             */
            inFile.close();
        } catch (IOException e)
        {
            throw new WSVException("Fehler beim lesen aus Datei", -1);
        }

        /*
         * Leerzeilen nach der Ausgabe
         */
        System.out.println("\n");
    }

    /**
     * Funktion zum ausleihen von Objekten
     * 
     * @author Steffen Krüger
     * @param String
     *            tokens
     * @throws WSVException 
     */
    private void ausleihen(String[] tokens) throws WSVException
    {
    	Functions.prüfeArrayLänge(3, tokens);
    	Lager lager = Lager.getInstance();
    	
    	/*
         * Namen splitten
         */
        String[] namen = Functions.verarbeiteNamen(tokens[2]);
        
        /*
         * Alles von einem Kunden Prüfen
         */
        KundenArchiv archiv = KundenArchiv.getInstance();
        int kundennummer 	= archiv.bekommeIndex(namen[0], namen[1]);
    	
        /*
         * Wurde ein Count oder ein Datum übergeben?
         */
        SimpleDateFormat df = new SimpleDateFormat("dd.MM.yy-HH:mm");
        String datum 		= df.format(new Date());
        int count 			= 1;
        
        if(tokens.length > 3)
        {
        	/*
             * Wurde ein Count übergeben?
             */
            if(tokens[3].toLowerCase().startsWith("c"))
            {
            	try
            	{
            		count = new Integer(tokens[3].substring(1));
            		if(count <= 0)
            		{
            		    throw new WSVException("Ungültige Anzahl: " + tokens[3], 1);
            		}
            	}
            	catch(NumberFormatException e)
            	{
            		throw new WSVException("Ungültige Anzahl: " + tokens[3], 1);
            	}
            	
            	/*
            	 * Wurde ein Datum Übergeben?
            	 */
            	if(tokens.length > 4)
            	{
            		try 
                	{
        				datum = Functions.prüfeDatum(tokens[4]);
        			} catch (ParseException e) 
        			{
        				throw new WSVException("Ungültiges Datum übergeben", 1);
        			}
            	}
            }
            else
            {
            	/*
            	 * Nur Datum übergeben
            	 */
            	try 
            	{
    				datum = Functions.prüfeDatum(tokens[3]);
    			} catch (ParseException e) 
    			{
    				throw new WSVException("Ungültiges Datum übergeben", 1);
    			}
            }
        }
        
        switch (tokens[1].toLowerCase())
        {
            case "handtuch":
            	lager.handtuchAusleihen(kundennummer, datum, count);
                break;
            case "surfbrett":
            	lager.surfbrettAusleihen(kundennummer, datum, count);
                break;
            case "schwimmflügel":
            	lager.schwimmflügelAusleihen(kundennummer, datum, count, false);
                break;
            default:
            	throw new WSVException("Ungültiger Typ: " + tokens[1], 1);
        }
    }

    /**
     * Funktion zum anzeigen von Kunden
     * 
     * @author Steffen Krüger
     * @param String
     *            tokens
     * @throws WSVException 
     */
    private void zeigeCustomer(String[] tokens) throws WSVException
    {
        Functions.prüfeArrayLänge(3, tokens);
        Lager lager = Lager.getInstance();
        
        switch (tokens[2].toLowerCase())
        {
            case "a":
            case "all":
            	KundenArchiv.getInstance().gebeKundenAus();
                break;
            default:
                /*
                 * Namen splitten
                 */
                String[] namen = Functions.verarbeiteNamen(tokens[2]);
                
                /*
                 * Alles von einem Kunden Prüfen
                 */
                lager.archivAusgeben(KundenArchiv.getInstance().bekommeIndex(namen[0], namen[1]), false);
                break;
        }
    }

    /**
     * Funktion zum anzeigen von Objekten
     * 
     * @author Steffen Krüger
     * @param String
     *            tokens
     * @throws WSVException 
     */
    private void zeigeObjekt(String[] tokens) throws WSVException
    {
    	Functions.prüfeArrayLänge(3, tokens);
        switch (tokens[2].toLowerCase())
        {
            case "a":
            case "all":
            	Lager.getInstance().leihstatusAusgeben();
                break;
            case "handtuch":
                Lager.getInstance().leihstatusAusgeben("Handtuch");
                break;
            case "surfbrett":
                Lager.getInstance().leihstatusAusgeben("Surfbrett");
                break;
            case "schwimmflügel":
                Lager.getInstance().leihstatusAusgeben("Schwimmflügel");
                break;
            default:
            	throw new WSVException("Ungültiger Typ: " + tokens[2], 1);
        }
    }

    /**
     * Funktion zum zurückgeben von Objekten
     * 
     * @author Steffen Krüger
     * @param String
     *            tokens
     * @throws WSVException 
     */
    private void zurückgeben(String[] tokens) throws WSVException
    {
    	Functions.prüfeArrayLänge(3, tokens);
    	
    	/*
         * Wurde ein Datum übergeben?
         */
        SimpleDateFormat df = new SimpleDateFormat("dd.MM.yy-HH:mm");
        String datum 		= df.format(new Date());
        
        /*
         * Namen splitten
         */
        String[] namen = Functions.verarbeiteNamen(tokens[2]);
    	
    	/*
    	 * Wurde ein Datum Übergeben?
    	 */
    	if(tokens.length > 3)
    	{
    		try 
        	{
				datum = Functions.prüfeDatum(tokens[3]);
			} catch (ParseException e) 
			{
				throw new WSVException("Ungültiges Datum übergeben", 1);
			}
    	}
    	
    	Lager lager = Lager.getInstance();
    	int kdn = KundenArchiv.getInstance().bekommeIndex(namen[0], namen[1]);
    	
        switch (tokens[1].toLowerCase())
        {
            case "handtuch":
            	lager.handtuchZurückgeben(kdn, datum);
                break;
            case "surfbrett":
            	lager.handtuchZurückgeben(kdn, datum);
                break;
            case "schwimmflügel":
            	lager.handtuchZurückgeben(kdn, datum);
                break;
            default:
            	throw new WSVException("Ungültiger Typ: " + tokens[1], 1);
        }
    }

    /**
     * Funktion zum abrechnen
     * 
     * @author Steffen Krüger
     * @param String
     *            tokens
     * @throws WSVException 
     */
    private void abrechnen(String[] tokens) throws WSVException
    {
    	/*
         * Länge des Arrays prüfen
         */
        Functions.prüfeArrayLänge(2, tokens, 3);
        String datum;
        String[] namen;
        
        /*
         * Abrechnen
         */
        Lager lager = Lager.getInstance();
        if(tokens.length > 2)
        {
        	try 
        	{
				datum = Functions.prüfeDatum(tokens[1]);
			} catch (ParseException e) 
			{
				throw new WSVException("Ungültiges Datum übergeben", 1);
			}
        	
            Functions.prüfeArrayLänge(3, tokens);
            
            /*
             * Namen splitten
             */
            namen = Functions.verarbeiteNamen(tokens[2]);
        }
        else
        {
        	/*
             * Mit übergebenem Datum zurückgeben
             */
            SimpleDateFormat df = new SimpleDateFormat("dd.MM.yy-HH:mm");
            datum 				= df.format(new Date());
            
        	/*
             * Namen splitten
             */
            namen = Functions.verarbeiteNamen(tokens[1]);
        }
        
        int kdn = KundenArchiv.getInstance().bekommeIndex(namen[0], namen[1]);

        lager.schwimmflügelAbrechnen(kdn, datum);
        lager.handtuchAbrechnen(kdn, datum);
        lager.surfbrettAbrechnen(kdn, datum);
    }

    /**
     * Funktion um einen Kunden hinzuzufügen
     * 
     * @author Steffen Krüger
     * @param String
     *            tokens
     * @throws WSVException 
     */
    private void kundenHinzufügen(String[] tokens) throws WSVException
    {
        /*
         * Länge des Arrays prüfen
         */
        Functions.prüfeArrayLänge(2, tokens, 2);

        /*
         * Namen splitten
         */
        String[] namen = Functions.verarbeiteNamen(tokens[1]);

        /*
         * Kunden hinzufügen
         */
        KundenArchiv archiv = KundenArchiv.getInstance();
        archiv.fügeKundeHinzu(namen[0], namen[1]);
    }
}